#ifndef _DRV_EC600S_SOCK_H
#define _DRV_EC600S_SOCK_H

//wangtao
//#include "rom/queue.h"
#include "LIB_List.h"
#include "EC600S_AT/AT_TCPIP.h"

#define OAF_INET    1


#define OSOL_SOCKET    1

#define OSO_RCVTIMEO    1
#define OSO_SNDTIMEO    2
#define OSO_RCVBUF      3
#define OSO_SNDBUF      4

#define OSOCK_RCVTIMEO    20000
#define OSOCK_SNDTIMEO    20000
#define OSOCK_RCVBUF      10
#define OSOCK_SNDBUF      10

#define OINADDR_ANY    "0.0.0.0"

#define SOCK_MAX         12

#pragma pack(1)
typedef enum {
    SS_FREE = 0,            //该socket还未分配
    SS_UNCONNECTED,         //未连向任何socket
    SS_CONNECTING,          //正在连接过程中
    SS_CONNECTED,           //已连向一个socket
    SS_DISCONNECTING        //正在断开连接的过程中
}socket_state;

typedef struct
{
    socket_state  state;  //socket state
    short   type;         //socket type
    unsigned long  flags; //socket flags
    int protocol;         //附加协议,0.字符型，1.hex型
    EC600S_ADDR local;    //本地地址
    EC600S_ADDR to;       //对端地址
    int sndto;            //发送超时时间,阻塞模式使用
    int rcvto;            //接收超时时间,阻塞模式使用
    int sndbuf;           //发送缓存,指的是发送数据元素个数
    int rcvbuf;           //接收缓存,指的是接收数据元素个数
}ST_SOCKET;

typedef struct data_rx_entry{
    int sock;
	U8 *data;    //接收数据
	int len;     //接收数据长度
	int tick;
    EC600S_ADDR from;//远端地址,udp显示
	TAILQ_ENTRY(data_rx_entry) elements;
}ST_DATA_RX_ENTRY;

typedef struct data_tx_entry{
    int sock;
	U8 *data;    //发送数据
	int len;     //发送数据长度
	int tick;
    EC600S_ADDR to;//远端地址,udp显示
	TAILQ_ENTRY(data_tx_entry) elements;
}ST_DATA_TX_ENTRY;

#pragma pack()

/**
@brief sock初始化
@return 0成功，非0失败
**/
int Ec600sSockInit();
/**
@brief 更新套接字状态
@param s 套接字描述符
@param st 套接字状态
@return 0成功，非0失败
**/
int Ec600sSockStSet(int s, socket_state st);

/**
@brief ec600s重启更新套接字组状态
@param st 套接字状态
@return 0成功，非0失败
**/
int Ec600sSockStUpdate();

/**
@brief 套接字URC数据接收回调处理函数
@param sock 套接字描述符
@param data 接收数据
@param length 接收数据长度
@return 0成功，非0失败
**/
int Ec600sSockUrcCallback(int sock, U8 data[], int length);
/**
@brief 套接字主函数
@return 0成功，非0失败
**/
int Ec600sSockLoop(void);

/**
@brief 创建套接字
@param af 协议族
@param type 协议类型
@param protocol 附加协议.0.字符型数据,1.hex数据
@return 分配的套接字ID
**/
int Ec600sSocket( int af, int type, int protocol);
/**
@brief 绑定本地端口
@param s 套接字描述符
@param addr 本地地址
@param addrlen 地址长度
@return 0成功,非0失败
**/
int Ec600sBind(int s, const EC600S_ADDR *addr, int addrlen);
/**
@brief tcp客户端连接服务器
@param s 套接字描述符
@param addr 服务器地址
@param addrlen 地址长度
@return -1.非法套接字
**/
int Ec600sConnect(int s, const EC600S_ADDR *addr, int addrlen);

/**
@brief TCP服务端调用,开始监听
@param s 套接字描述符
@param backlog
@return 0成功,非0失败
**/
int Ec600sListen(int s, int backlog);

/**
@brief TCP服务端调用,接收TCP客户端的连接
@param s 套接字描述符
@param addr 地址
@param addrlen 地址长度
@return 0成功,非0失败
**/
int Ec600sAccept(int s, EC600S_ADDR *addr, int *addrlen);

/**
@brief 关闭套接字关闭连接
@param s 套接字描述符
@return 0成功，-1非法套接字
**/
int Ec600sClose(int s);
/**
@brief 关闭套接字关闭连接
@param s 套接字描述符
@param buf 发送数据
@param len 发送数据长度
@return >=0接收数据长度,<0错误码
**/
int Ec600sRecv(int s, char *buf, int len, int flags);

/**
@brief TCP调用
@param s 套接字描述符
@param buf 发送数据
@param len 发送数据长度
@param flags 调用执行方式.0:不阻塞,1:阻塞
@return >=0发送字节数，-1.非法套接字,-2.open失败,-3.sndbuf满,-4.发送超时,-5.内存申请失败,-6.网络断开
**/
int Ec600sSend(int s, char *buf, int len, int flags);

/**
@brief UDP调用
@param s 套接字描述符
@param buf 接收缓存
@param len 接收缓存长度
@param flags 调用执行方式.0:不阻塞,1:阻塞
@param from 对端地址
@param addrlen 地址长度
@return >=0发送字节数，<0错误
**/
int Ec600sRecvfrom(int s, char *buf, int len, int flags, EC600S_ADDR *from, int *addrlen);

/**
@brief UDP调用
@param s 套接字描述符
@param buf 发送数据
@param len 发送数据长度
@param flags 调用执行方式.0:不阻塞,1:阻塞
@param addr 服务器地址
@param addrlen 地址长度
@return >=0发送字节数，-1.非法套接字,-2.open失败,-3.sndbuf满,-4.发送超时,-5.内存申请失败,-6.网络断开
**/
int Ec600sSendto(int s, char *buf, int len, int flags, EC600S_ADDR *to, int addrlen);
/**
@brief 设置套接字选项
@param s 套接字描述符
@param level 设置级别
@param optname 选项名称
@param optval 选项值
@param optlen 选项值长度
@return >=0发送字节数，<0错误
**/
int Ec600sSetsockopt(int s, int level, int optname, const void *optval, int optlen);

#endif

